;; sprdplot.lsp - from update\\enhance-sprdplt1.lsp
;; Copyright (c) 1996-2002 by Forrest W. Young, Richard A. Faldowski, & Carla Bann

;;SpreadPlot constructor function

(defun spreadplot 
  (plot-matrix &key supplemental-plot statistical-object (menu-title "SpreadPlot") show 
               (local-links t) (container *spreadplot-container*) (location nil)
               (size (floor (* .9 (effective-screen-size))))
               rel-widths rel-heights span-right span-down)
"Method Args: PLOTMATRIX &KEY CONTAINER *SPREADPLOT-CONTAINER*) SPAN-RIGHT SPAN-DOWN REL-WIDTHS REL-HEIGHTS (LOCAL-LINKS T) STATISTICAL-OBJECT (MENU-TITLE \"SpreadPlot\") (SHOW NIL) (SIZE (EFFECTIVE-SCREEN-SIZE)) SUPPLEMENTAL-PLOT
The SPREADPLOT function creates and returns a spreadplot. The arguments are as follows:
  PLOTMATRIX is a matrix of plot or dialog box objects (called plot-objects). The plot-objects in PLOTMATRIX are assumed to already exist and to have all been created while CONTAINER was enabled (all must have the same container, which must be CONTAINER). SPREADPLOT then arranges  these plots inside CONTAINER in a rectangular array according to the details described below. 
  Usually there is one object per matrix cell, in which case the objects are laid out adjacent to each other, one per cell, in a rectangular array. There may be more than one object per matrix cell. When there is, the objects in the cell are laid out on top of each other, the last one being shown initially. To allow for cell-spanning (see below) there may be no object in a matrix cell (i.e., the matrix cell may be nil). The first row and column cannot contain nil values.
  SPAN-RIGHT and SPAN-DOWN are each a matrix whose elements specify whether a plot occupies more than a single plotcell within a row or column. Each entry must be a non-negative integer indicating how many cells are spanned, counting from the current plotcell. Plotcells which are nil (are spanned and have no plot) have a span value of zero. 
  Plots are all same width and height unless REL-WIDTHS or REL-HEIGHTS are used (REL-WIDTHS and REL-HEIGHTS must be a list of nr or nc values, respectively, where nr=number of spreadplot rows and nc=number of columns). Column widths are proportional to the REL-WIDTHS values, row-heights to the REL-HEIGHTS values.
  The spreadplot is contained within CONTAINER whose size is not greater than SIZE. Due to aspect-ratio constraints the size may be smaller than SIZE. By default, SIZE is equal to the usable portion of the screen (the part not occupied by MS-Windows toolbars). This size is calculated by the (EFECTIVE-SCREEN-SIZE) function. The plots are shown if SHOW is T (the default is NIL). 
  SUPPLEMENTAL-PLOT is a plot or dialog box object. SUPPLEMENTAL-PLOT is located adjacent to the upper right edge of the PLOTMATRIX.  The spreadplot cells consist of objects identified in PLOTMATRIX, plus, if not nil, SUPPLEMENTAL-PLOT. Note that containers and the supplemental plot do not yield an ascethetically pleasing result!
  When LOCAL-LINKS is T (the default value), the spreadplot plots can be linked only to themselves, and not to other plots. They can be linked to other plots otherwise (even hidden plots). 
  STATISTICAL-OBJECT is an optional object identification of the model or data object that is creating the spreadplot (nil, the default, when there is none). 
  MENU-TITLE specifies the title of the spreadplot menu (nil for no menu).  


Here is the general idea for how spreadplot messaging works: 

When a plot in a spreadplot experiences some change, it sends a message to the spreadplot about the details of the change. Then, if the message needs to be processed by the spreadplot's statistical object (i.e., its model, transf, or data object) the spreadplot in turn relays this same message to the statistical object so that it knows that a change has been made and what the change is. Then the statistical object processes the message and sends the results to the spreadplot. Then the spreadplot broadcasts either the original (when the statistical object isn't used) or the results of the processed original message (when the statistical object was used) to every plot in the spreadplot. 

The specific messages that do this, and the sequence of actions, is as follows:

1) An individual plot begins the process by sending the 
          :UPDATE-SPREADPLOT (i j &rest args &key (use-statobj nil))
message to the spreadplot. If USE-STATOBJ is T then the message is relayed to the statistical object which processes it and sends the results back via another UPDATE-SPREADPLOT message in which USE-STATOBJ must be NIL, and which must have the same values for values I and J. When USE-STATOBJ is NIL, the message is broadcast via the update-plotcell message to all plots so that they can update themselves. The arguments I and J are two numbers which identify the message uniquely, usually the row and column of the sending plotcell, but if a plotcell can send more than one type of message than another identifing method must be used. All of the REST arguments must be a union of arguments needed by all receiving plotcells, each of which must decide which arguments it needs.

Steps 2 and 3 are skipped unless USE-STATOBJ is T

2) When USE-STATOBJ was T in the preceeding step, the spreadplot object sends
          :UPDATE-STATOBJ (I J &REST ARGS)
to STATOBJ with the same arguments as were sent to the spreadplot (except for USE-STATOBJ). The particular statistical object needs to have an :update-statobj method written.

3) The statistical object sends the
          :UPDATE-SPREADPLOT (i j &rest args)
to the speadplot. Here I and J must be the same as were received by the statistical object, but args has changed. USE-STATOBJ must not be used.

4) The spreadplot object broadcasts the
          :UPDATE-PLOTCELL (i j &rest args)
message to all of its plots. Each plot that needs to respond to the message must have a unique UPDATE-PLOTCELL message written. They need to know how to respond to only certain I-J messages, not all. Args is either what was sent by the originating plotcell or the statistical object. Near the beginning of the sprdplot.lsp file is a dummy :update-plotcell method which is defined for all graphs and dialogs and which does nothing except ignore any messages that are sent."

  (let* ((nrows (array-dimension plot-matrix 0))
         (ncols (array-dimension plot-matrix 1))
         (result (dotimes (i nrows)
                  (dotimes (j ncols)
                   (unless (aref plot-matrix i j)
                           (setf (aref plot-matrix i j)
                                 (send graph-window-proto :new :show nil))))))
        (splot (send spreadplot-proto :new 
                     :plot-matrix plot-matrix
                     :supplemental-plot supplemental-plot
                     :statistical-object statistical-object
                     :span-right span-right 
                     :span-down span-down
                     :local-links local-links 
                     :menu-title menu-title
                     :show show
                     :container container
                     :screen-size (send *vista* :spreadplot-sizes)
                     :rel-widths rel-widths
                     :rel-heights rel-heights)))
    splot))


(defun spread-plot (&rest args) (apply #'spreadplot args))

(defmeth graph-window-proto :update-plotcell (i j args)
"Method Args: I J ARGS
Method to update a plotcell. This is the default nil method. Replacement methods must be written for individual plotcells which are to be updated. The replacement methods will be sent information by the update-spreadplot method. This information includes I and J to indicate the row and column of the  sending plotcell. The information also includes ARGS, a list of the union of the arguments that are needed by each receiving plotcell. Each plotcell must decide which arguments it needs."
    nil)

(defmeth dialog-proto :update-plotcell (i j args))

;Define prototype spreadplot and its isnew method

(defproto spreadplot-proto 
  '(plot-matrix supplemental-plot statistical-object menu menu-title window-menu-item
    menu-template link-list locations-matrix sizes-matrix container
    show showing screen-size span-right span-down cell-size size location
    title rel-widths rel-heights suploc ever-shown?))

;changes made to fix spreadplot menu by fwy 20010329

(defmeth spreadplot-proto :isnew 
  (&key statistical-object 
        supplemental-plot
        plot-matrix
        local-links
        menu-title  
        show
        screen-size
        span-right
        container
        span-down
        rel-widths
        rel-heights
        (menu-template '(dash dash dash)) )
  (send *watcher* :write-text "SpreadPlot")
  (when (not statistical-object) (setf statistical-object *current-object*))
  (send self :statistical-object statistical-object)
  
  (unless (send statistical-object :has-slot 'spreadplot-object)
          (send statistical-object :add-slot 'spreadplot-object)
          (defmeth statistical-object :spreadplot-object (&optional (obj nil set))
            (if set (setf (slot-value 'spreadplot-object) obj))
            (slot-value 'spreadplot-object)))
      
  (send statistical-object :spreadplot-object self)
  (send self :supplemental-plot supplemental-plot)

  (when supplemental-plot
        (when (kind-of-p supplemental-plot dialog-proto)
              (send (aref plot-matrix 0 0) 
                    :add-subordinate supplemental-plot)))
  (let* ((nrows (array-dimension plot-matrix 0))
         (ncols (array-dimension plot-matrix 1)))
    (send self :span-right (if span-right span-right
                               (make-array (list nrows ncols) :initial-element 1)))
    (send self :span-down (if span-down span-down
                              (make-array (list nrows ncols) :initial-element 1)))
    (setf span-right (send self :span-right))
    (setf span-down  (send self :span-down ))
    (send self :show show)
    (send self :screen-size screen-size)
    (send *vista* :spreadplot-sizes screen-size)
    (send self :rel-heights 
          (if rel-heights 
              (combine (map-elements #'repeat rel-heights (second (size plot-matrix))))
              (setf rel-heights (repeat 1 (prod (size plot-matrix))))))
    (send self :rel-widths 
          (if rel-widths 
              (repeat rel-widths (first (size plot-matrix)))
              (repeat 1 (prod (size plot-matrix)))))  

    (if menu-title (send self :menu t) (send self :menu nil))
    (send self :menu-title menu-title)
    (send self :menu-template menu-template)
    (setf *current-spreadplot* self)
    (setf splot-type (if (equal *current-object* *current-data*)
                         (send $ :data-type) 
                         (send statistical-object :title)))
    (setf splot-data (if (equal *current-object* *current-data*)
                         (send $ :name)
                         (send (send statistical-object :data-object) :name)))
    (send self :title (strcat (string-capitalize splot-type) " SpreadPlot for " splot-data))
    (if local-links (send self :make-link-list (combine plot-matrix )))
    (setf container  (if container container *spreadplot-container*))
    (send self :container (if container container *spreadplot-container*))
    (send self :plot-matrix plot-matrix)
    (send self :create-spreadplot)
    (when menu-title (send self :create-menu menu-title))
    #+containers
    (progn
     (send *watcher* :write-text "SpreadPlot Container")
     (send container :title (send self :title))
     (send container :add-slot 'spreadplot-object self)
     (defmeth container :spreadplot-object (&optional (objd nil set))
       (if set (setf (slot-value 'spreadplot-object) objid))
       (slot-value 'spreadplot-object))
     (defmeth container :max-window ()
       (send self :show-window)
       (send self :fix-splot-size))
     (defmeth container :show-spreadplot () (send self :show-window))

     (defmeth container :close ()
       (call-next-method)
       (let ((item (send (send self :spreadplot-object) :window-menu-item))
             )
         (when item (send *desktop-window-menu* :delete-items item))
         (send (send self :spreadplot-object) :remove)
         (send self :remove))
       ))

    (mapcar #'(lambda (plot)
                (defmeth plot :close () 
                  ;(send self :pop-out nil) 
                  ;(send self :restore)
                  (let ((overlay (send self :button-overlay)))
                    (when (send overlay :zoom-state) 
                          (send overlay :zoom-state nil)
                          (send self :zoom-zip nil))
                    (when (send overlay :pop-state) 
                          (send overlay :switch-pop-state)
                          (send self :pop-out nil))
                    ))
                (send plot :add-slot 'spreadplot-object self )
                (defmeth plot :spreadplot (&optional (objid nil set))
                  (if set (setf (slot-value 'spreadplot-object) objid))
                  (slot-value 'spreadplot-object))
                (defmeth plot :spreadplot-object (&optional (objid nil set))
                  (if set (setf (slot-value 'spreadplot-object) objid))
                  (slot-value 'spreadplot-object))
                (unless (send plot :has-slot 'statistical-object)
                        (send plot :add-slot 'statistical-object)
                        (defmeth plot :statistical-object (&optional (objid nil set))
                          (if set (setf (slot-value 'statistical-object) objid))
                          (slot-value 'statistical-object)))
                 (send plot :statistical-object statistical-object)
                 )
            (send self :all-plots))
    (dotimes 
     (i nrows)
     (dotimes 
      (j ncols)
      (when (or (and (integerp (aref span-right i j)) (= 0 (aref span-right i j)))
                (and (integerp (aref span-down  i j)) (= 0 (aref span-down  i j))))
            (defmeth (aref plot-matrix i j) :show-window ()))))
    

   ; (send *watcher* :write-text "SpreadPlot Constructed")
   ; (send *desktop-spreadplot-menu-item* :enabled t)
    (let ((window-menu-item  
           (send menu-item-proto :new (send self :title)
                 :action #'(lambda () (send self :bring-to-top))))
          ;(statobj-popup-menu-item  
          ; (send menu-item-proto :new (send self :title)
          ;       :action #'(lambda () (send self :bring-to-top))))
          )
      (send *desktop-window-menu* :append-items window-menu-item)
     ; (send self :statobj-menu-item statobj-menu-item)
      (send self :window-menu-item window-menu-item))
    (when show (send self :show-spreadplot))
    ))


(defmeth spreadplot-proto :statistical-object (&optional (obj-id nil set))
"Method Args:  &optional (obj-id nil) 
Sets or retrieves the object id# of the statistical object for which the spreadplot is installed."
  (if set (setf (slot-value 'statistical-object) obj-id))
  (slot-value 'statistical-object) )

(defmeth spreadplot-proto :container (&optional (obj-id nil set))
"Method Args:  &optional (obj-id nil) 
Sets or retrieves the container object id of the container which contains the spreadplot."
  (if set (setf (slot-value 'container) obj-id))
  (slot-value 'container) )

(defmeth spreadplot-proto :plot-matrix (&optional (matrix nil set))
"Method Args:  &optional PLOT-MATRIX
Sets or retrieves the spreadplot's matrix of plot object ids."
  (if set (setf (slot-value 'plot-matrix) matrix))
  (slot-value 'plot-matrix) )

(defmeth spreadplot-proto :supplemental-plot (&optional (obj-id nil set))
"Method Args:  &optional (obj-id nil) 
Sets or retrieves the object id# of the supplemental plot"
  (if set (setf (slot-value 'supplemental-plot) obj-id))
  (slot-value 'supplemental-plot) )

(defmeth spreadplot-proto :locations-matrix (&optional (matrix nil set))
"Method Args:  &optional LOCATIONS-MATRIX
Sets or retrieves the spreadplot's matrix of plot locations (excluding supplemental plot)."
  (if set (setf (slot-value 'locations-matrix) matrix))
  (slot-value 'locations-matrix) )

(defmeth spreadplot-proto :span-right (&optional (matrix nil set))
"Method Args:  &optional span-right
Sets or retrieves the spreadplot's matrix of span-right integers."
  (if set (setf (slot-value 'span-right) matrix))
  (slot-value 'span-right) )

(defmeth spreadplot-proto :span-down (&optional (matrix nil set))
"Method Args:  &optional span-down
Sets or retrieves the spreadplot's matrix of span-down integers."
  (if set (setf (slot-value 'span-down) matrix))
  (slot-value 'span-down) )

(defmeth spreadplot-proto :suploc (&optional (list nil set))
"Method Args:  &optional LOCATIONS-MATRIX
Sets or retrieves the supplemental plot location."
  (if set (setf (slot-value 'suploc) list))
  (slot-value 'suploc) )

(defmeth spreadplot-proto :cell-size (&optional (list nil set))
"Method Args:  &optional CELL-SIZE
Sets or retrieves the spreadplot's basic plotcell size. All plots have sizes that are proportional to these two values."
  (if set (setf (slot-value 'cell-size) list))
  (slot-value 'cell-size) )

(defmeth spreadplot-proto :size 
  (&optional (w nil used-w?) (h nil used-h?))
"Method Args:  &optional W H or (list W H)
Retrieves the spreadplot's size, or sets the size of an area in which the spreadplot will be contained."
  (when used-w?
        (cond 
          ((and used-h? (integerp w) (integerp h))
           (setf (slot-value 'size) (list w h)))
          ((and (not used-h?) (listp w))
           (setf (slot-value 'size) w))
          (t
           (error "SpreadPlot Size: Arguments may be either W and H or (LIST W H)"))))
  (slot-value 'size))

(defmeth spreadplot-proto :location 
  (&optional (x nil used-x?) (y nil used-y?))
"Method Args:  &optional X Y or (list X Y)
Retrieves or sets and reports the spreadplot's location."
  (when used-x?
        (cond 
          ((and used-y? (integerp x) (integerp y))
           (setf (slot-value 'location) (list x y)))
          ((and (not used-y?) (listp x))
           (setf (slot-value 'location) x))
          (t
           (error "SpreadPlot Size: Arguments may be either X and Y or (LIST X Y)"))))
  (slot-value 'location))

(defmeth spreadplot-proto :sizes-matrix (&optional (matrix nil set))
"Method Args:  &optional sizes-matrix
Sets or retrieves the matrix of sizes of all plots (excluding supplemental plot)."
  (if set (setf (slot-value 'sizes-matrix) matrix))
  (slot-value 'sizes-matrix) )

(defmeth spreadplot-proto :screen-size (&optional (list nil set))
"Method Args:  &optional screen-SIZE
Sets or retrieves the size of the screen to be occupied by the spreadplot."
  (if set (setf (slot-value 'screen-size) list))
  (slot-value 'screen-size) )

(defmeth spreadplot-proto :rel-widths (&optional (list nil set))
"Method Args:  &optional rel-widths
Sets or retrieves the relative widths of the plot-cells."
  (if set (setf (slot-value 'rel-widths) list))
  (slot-value 'rel-widths) )

(defmeth spreadplot-proto :rel-heights (&optional (list nil set))
"Method Args:  &optional rel-heights
Sets or retrieves the relative heights of the plot-cells."
  (if set (setf (slot-value 'rel-heights) list))
  (slot-value 'rel-heights) )

(defmeth spreadplot-proto :link-list (&optional (list nil set))
"Method Args:  &optional link-list
Sets or retrieves the list of linked plot-cells."
  (if set (setf (slot-value 'link-list) list))
  (slot-value 'link-list) )

(defmeth spreadplot-proto :menu (&optional (values nil set))
"Method Args:  &optional MENU
Sets or retrieves the spreadplot's menu in its MENU slot."
  (if set (setf (slot-value 'menu) values))
  (slot-value 'menu) )

(defmeth spreadplot-proto :window-menu-item (&optional (values nil set))
"Method Args:  &optional window-menu-item
Sets or retrieves the spreadplot's window menu item object id."
  (if set (setf (slot-value 'window-menu-item) values))
  (slot-value 'window-menu-item) )

(defmeth spreadplot-proto :show (&optional (logical nil set))
"Method Args:  &optional show
Sets or retrieves whether to show the spreadplot."
  (if set (setf (slot-value 'show) logical))
  (slot-value 'show) )

(defmeth spreadplot-proto :showing (&optional (logical nil set))
"Method Args:  &optional show
Sets or retrieves whether the spreadplot is showing."
  (if set (setf (slot-value 'showing) logical))
  (slot-value 'showing) )

(defmeth spreadplot-proto :ever-shown? (&optional (logical nil set))
"Method Args:  &optional show
Sets or retrieves whether the spreadplot has ever been shown before."
  (if set (setf (slot-value 'ever-shown?) logical))
  (slot-value 'ever-shown?) )

(defmeth spreadplot-proto :menu-title (&optional (values nil set))
"Method Args:  &optional ''TITLE''
Sets or retrieves the title of the spreadplot's menu."
  (if set (setf (slot-value 'menu-title) values))
  (slot-value 'menu-title) )

(defmeth spreadplot-proto :menu-template (&optional (values nil set))
"Method Args:  &optional TEMPLATE
Sets or retrieves the template of items for the spreadplot's menu."
  (if set (setf (slot-value 'menu-template) values))
  (slot-value 'menu-template) )

(defmeth spreadplot-proto :title (&optional (values nil set))
"Method Args:  &optional ''TITLE''
Sets or retrieves the title of the spreadplot."
  (if set (setf (slot-value 'title) values))
  (slot-value 'title) )

(defmeth spreadplot-proto :create-spreadplot ()
  (send *watcher* :write-text "SpreadPlot Layout")
  (let* ((plot-matrix (send self :plot-matrix))
         (supplot (send self :supplemental-plot))
         (dash (send dash-item-proto :new))
         (nrows (first (size plot-matrix)))
         (ncols (second (size plot-matrix)))
         (relw (matrix (list nrows ncols) (send self :rel-widths)))
         (relh (matrix (list nrows ncols) (send self :rel-heights)))
         (totw (sum relw))
         (toth (sum relh))
         (show (send self :show))
         (plot-size nil)
         (tot-size '(0 0))
         (sp self)
         (sp-screen-size (- (send self :screen-size)(list 8 0) ))
         (sp-screen-size (send self :screen-size))
         (container (send self :container))
         (locations-matrix (make-array (list nrows ncols)))
         (sizes-matrix (make-array (list nrows ncols)))
         (plot nil)
         (plots nil)
         (k 0)
         (plot00 (aref plot-matrix 0 0))
         (window-decoration-width 8)
         (window-decoration-height 28)
         (span-right (send self :span-right))
         (span-down (send self :span-down))
         (spans)
         (span-val)
         (cell-sizes)
         )
    (when (listp plot00) (setf plot00 (first plot00)))
    (when (< nrows 1) (error "SpreadPlots must have at least one row"))
    (when (< ncols 1) (error "SpreadPlots must have at least one column"))
    (if (not sp-screen-size) (setf sp-screen-size screen-size))
    (setf plot-size  
          (min (- (floor (/ (first sp-screen-size) 
                            (/ totw nrows))) ;ncols
                  window-decoration-width 6)
               (- (floor (/ (- (second sp-screen-size) menu-bar-height)
                            (/ toth ncols))) ;nrows
                  msdos-fiddle border-thickness ;msdos-fiddle
#+X11                  60
                  (/ window-decoration-height 2))))
    
    
    
    (dotimes (i nrows)
             (dotimes (j ncols)
                      (setf mat-size
                            (list
                             (floor (* (aref relw i j) 
                                       (+ plot-size window-decoration-width)))
                             (floor (* (aref relh i j) plot-size))))
                      (setf (aref sizes-matrix i j) mat-size)
                      (setf tot-size (+ tot-size mat-size))))
    (send self :sizes-matrix sizes-matrix)
    (send *watcher* :write-text "SpreadPlot Locations")
    (dotimes (i nrows)
             (setf cum-height
                   (if (= i 0) 24
                       (+ 24 (second (apply #'+ 
                                     (coerce 
                                      (first 
                                       (column-list 
                                        (select sizes-matrix (iseq i) 0 )))
                                      'list))))))
             (dotimes (j ncols)
                      (setf cum-width
                            (if (= j 0) 4
                                (+ 4 (first (apply #'+ 
                                              (coerce 
                                               (first 
                                                (row-list 
                                                 (select sizes-matrix 0 (iseq j) ))) 
                                               'list))))))
                      (setf (aref locations-matrix i j)
                            (list (+ cum-width  (* j (+ window-decoration-width)))
                                  (+ cum-height (* i (+ window-decoration-height)))))))
    (send self :locations-matrix locations-matrix)
    (when (> ncols 1)
          (setf spans span-right)
          (when (> (length (remove-duplicates (combine spans))) 1)
                (setf span-val nil)
                (setf cell-sizes nil)
                (dotimes (i nrows)
                         (dotimes (j ncols)
                                  (setf span-val (aref spans i j))
                                  (when (listp span-val) (setf span-val (first span-val)))
                                  (when (> span-val 1)
                                        (when (= j ncols) (error "Span Error"))
                                        (setf cell-sizes (aref sizes-matrix i j))
                                        (setf (aref sizes-matrix i j)
                                              (list (* span-val (+ 4 (first cell-sizes)))
                                                    (second cell-sizes))))))))
    (when (> nrows 1)
          (setf spans span-down)
          (when (> (length (remove-duplicates (combine spans))) 1)
                (setf span-val nil)
                (setf cell-sizes nil)
                (dotimes (j ncols)
                         (dotimes (i nrows)
                                  (setf span-val (aref spans i j))
                                  (when (listp span-val) (setf span-val (first span-val)))
                                  (when (> span-val 1)
                                        (when (= i nrows) (error "Span Error"))
                                        (setf cell-sizes (aref sizes-matrix i j))
                                        (setf (aref sizes-matrix i j)
                                              (list (first cell-sizes)
                                                    (+ (* (1- span-val) 20)
                                                       (* span-val (+ 4 (second cell-sizes))))
                                                    )))))))
    (send self :span-right span-right)
    (send self :span-down  span-down )
    (dotimes (i nrows) 
             (dotimes (j ncols) 
                      (setf plots (aref plot-matrix i j))
                      (when (and (listp plots) (not (listp (aref span-right i j))))
                            (let* ((span-val-right (aref span-right i j))
                                   (span-val-down  (aref span-down  i j))
                                   (nplts (length plots)))
                              (setf (aref span-right i j) (repeat span-val-right nplts))
                              (setf (aref span-down  i j) (repeat span-val-down  nplts)))
                            )
                      (if (not (listp plots)) (setf plots (list plots)))
                      (dotimes (L (length plots)) 
                               (setf plot (select plots L))
                               (unless (send plot :has-slot 'spreadplot-object)
                                       (send plot :add-slot 'spreadplot-object) 
                                       (defmeth plot :spreadplot-object 
                                                        (&optional (objid nil set)) 
                                         (if set (setf (slot-value 'spreadplot-object) objid)) 
                                         (slot-value 'spreadplot-object)))
                               (send plot :spreadplot-object self)
                               (apply #'send plot :size (aref sizes-matrix i j))
                               (apply #'send plot :location (aref locations-matrix i j)))))


    (when supplot
          (send *watcher* :write-text "SpreadPlot Supplemental Plot")
          (let* ((upright (first (1- (array-dimensions (send self :plot-matrix))))) 
                 (upright-loc (select (send self :locations) upright)) 
                 (upright-size (select (send self :sizes) upright)) 
                 (sup-loc (+ upright-loc 
                             (list (+ window-decoration-width (first upright-size)) 0))))
            (apply #'send supplot :location sup-loc) 
            (defmeth supplot :close () (send plot00 :close)) 
            (send supplot :add-slot 'spreadplot-object self) 
            (defmeth supplot :spreadplot-object (&optional (objid nil set)) 
              (if set (setf (slot-value 'spreadplot-object) objid)) 
                  (slot-value 'spreadplot-object))))

    (send self :calculate-splot-size)

    (defmeth plot00 :close ()
      (send sp :hide-spreadplot))

    (if (equal (send (first (last (send *help-menu* :items))) :title) "-")
        (setf dash nil)
        (send *help-menu* :append-items dash))

    )) 